


#ifndef PF_ENTITYCONTAINER_H
#define PF_ENTITYCONTAINER_H

#include "pf_arc.h"
#include "pf_circle.h"
#include "pf_ellipse.h"
#include "pf_entity.h"
#include "pf_line.h"
#include "pf_point.h"
#include "lx_Export.h"

/**
 * Class representing a tree of entities.
 * Typical entity containers are graphics, polylines, groups, texts, ...)
 *

 */
class LX_EXPORT PF_Container : public PF_Entity {

public:

    PF_Container(PF_Container* parent=NULL, bool owner=true);
    //PF_EntityContainer(const PF_EntityContainer& ec);
    virtual ~PF_Container();

    virtual PF_Entity* clone();
    virtual void detach();

    /** @return LX_Define::EntityContainer */
    virtual LX_Define::EntityType rtti() const {
        return LX_Define::EntityContainer;
    }
	
    void reparent(PF_Container* parent);

    /**
     * @return true: because entities made from this class
     *         and subclasses are containers for other entities.
     */
    virtual bool isContainer() const {
        return true;
    }
	
    /**
     * @return false: because entities made from this class
     *         and subclasses are containers for other entities.
     */
    virtual bool isAtomic() const {
		return false;
	}
	
	virtual double getLength();

    virtual void undoStateChanged(bool undone);
    virtual void setVisible(bool v);

    virtual bool setSelected(bool select=true);
    virtual bool toggleSelected();

    virtual void selectWindow(PF_Vector v1, PF_Vector v2, 
		bool select=true, bool cross=false);

    virtual void addEntity(PF_Entity* entity);
    virtual void insertEntity(int index, PF_Entity* entity);
//RLZ unused    virtual void replaceEntity(int index, PF_Entity* entity);
    virtual bool removeEntity(PF_Entity* entity);
    virtual PF_Entity* firstEntity(LX_Define::ResolveLevel level=LX_Define::ResolveNone);
    virtual PF_Entity* lastEntity(LX_Define::ResolveLevel level=LX_Define::ResolveNone);
    virtual PF_Entity* nextEntity(LX_Define::ResolveLevel level=LX_Define::ResolveNone);
    virtual PF_Entity* prevEntity(LX_Define::ResolveLevel level=LX_Define::ResolveNone);
    virtual PF_Entity* entityAt(int index);
//RLZ unused	virtual int entityAt();
	virtual int findEntity(PF_Entity* entity);
    virtual void clear();

    QListIterator<PF_Entity*> createIterator();

    //virtual unsigned long int count() {
	//	return count(false);
	//}
    virtual bool isEmpty() {
        return count()==0;
    }
    virtual unsigned long int count();
    virtual unsigned long int countDeep();
    //virtual unsigned long int countLayerEntities(PF_Layer* layer);
    virtual unsigned long int countSelected();

    /**
     * Enables / disables automatic update of borders on entity removals
     * and additions. By default this is turned on.
     */
    virtual void setAutoUpdateBorders(bool enable) {
        autoUpdateBorders = enable;
    }
    virtual void adjustBorders(PF_Entity* entity);
    virtual void calculateBorders();
    virtual void forcedCalculateBorders();
    virtual void updateDimensions();
    virtual void updateInserts();
    virtual void updateSplines();
    virtual void update();
        virtual void renameInserts(const QString& oldName,
                const QString& newName);


    virtual PF_Vector getNearestEndpoint(const PF_Vector& coord,
                                         double* dist = NULL);

    PF_Entity* getNearestEntity(const PF_Vector& point,
                                double* dist = NULL,
                                LX_Define::ResolveLevel level=LX_Define::ResolveAll);

    virtual PF_Vector getNearestPointOnEntity(const PF_Vector& coord,
            bool onEntity = true,
			double* dist = NULL,
            PF_Entity** entity=NULL);

    virtual PF_Vector getNearestCenter(const PF_Vector& coord,
                                       double* dist = NULL);
    virtual PF_Vector getNearestMiddle(const PF_Vector& coord,
                                       double* dist = NULL);
    virtual PF_Vector getNearestDist(double distance,
                                     const PF_Vector& coord,
                                     double* dist = NULL);
    virtual PF_Vector getNearestIntersection(const PF_Vector& coord,
            double* dist = NULL);
    virtual PF_Vector getNearestRef(const PF_Vector& coord,
                                     double* dist = NULL);
    virtual PF_Vector getNearestSelectedRef(const PF_Vector& coord,
                                     double* dist = NULL);
			
    virtual double getDistanceToPoint(const PF_Vector& coord,
                                      PF_Entity** entity,
                                      LX_Define::ResolveLevel level=LX_Define::ResolveNone,
				      double solidDist = LX_DOUBLEMAX);

    virtual bool optimizeContours();
	
	virtual bool hasEndpointsWithinWindow(PF_Vector v1, PF_Vector v2);
	
	virtual void move(PF_Vector offset);
    virtual void rotate(PF_Vector center, double angle);
    virtual void scale(PF_Vector center, PF_Vector factor);
    virtual void mirror(PF_Vector axisPoint1, PF_Vector axisPoint2);
	
    virtual void stretch(PF_Vector firstCorner,
                         PF_Vector secondCorner,
                         PF_Vector offset);
	virtual void moveRef(const PF_Vector& ref, const PF_Vector& offset);
	virtual void moveSelectedRef(const PF_Vector& ref, const PF_Vector& offset);

    virtual void draw(PF_Painter* painter, PF_GraphicView* view, double patternOffset=0.0);

    friend std::ostream& operator << (std::ostream& os, PF_Container& ec);

    bool isOwner() {return autoDelete;}
    void setOwner(bool owner) {autoDelete=owner;}

	
protected:
	/**
     * Automatically update the borders of the container when entities
     * are added or removed. 
     */
	static bool autoUpdateBorders;

    /** entities in the container */
    QList<PF_Entity *> entities;

    /** sub container used only temporarly for iteration. */
    PF_Container* subContainer;
private:
    int entIdx;
    bool autoDelete;
};

#endif
